package org.aceor.mddal.common.sqlparser.result.condition;

import com.google.common.base.Joiner;
import com.google.common.base.Objects;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by lxue on 16/3/23.
 */
public abstract class ComparableUnion extends ComparableUnit {
    protected List<ComparableUnit> comparableUnion = new ArrayList<ComparableUnit>(2);

    public ComparableUnion(Comparable<?> value, BinaryOperator binaryOperator) {
        super(value, binaryOperator);
        comparableUnion.add(new ComparableUnit(value,binaryOperator));
    }

    public ComparableUnion() {
        super();
    }

    public ComparableUnion(ComparableUnit comparableUnit) {
        super(comparableUnit.getValue(), comparableUnit.getBinaryOperator());
        comparableUnion.add(comparableUnit);
    }

    public void addComparableUnit(ComparableUnit comparableUnit) {
        comparableUnion.add(comparableUnit);
    }

    public ComparableUnit fillValue() {
        try {
            Constructor<? extends ComparableUnion> con =  this.getClass().getConstructor((Class[])null);
            ComparableUnion union = con.newInstance((Object[])null);
            for(ComparableUnit unit : comparableUnion){
                union.addComparableUnit(unit.fillValue());
            }
            return union;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public List<ComparableUnit> getComparableUnion() {
        return comparableUnion;
    }

    abstract protected String getRelation();

    @Override
    public String toString() {
        if (comparableUnion.isEmpty()) {
            throw new NullPointerException("ComparableUnion为空");
        }
        Object[] args = new Object[comparableUnion.size() * 2 - 1];
        int index = 0;
        for (ComparableUnit comparableUnit : comparableUnion) {
            if (0 != index) {
                args[index++] = getRelation();
            }
            args[index++] = comparableUnit;
        }
        return Joiner.on("").join(args);
    }

    public boolean containsComparableUnit(ComparableUnit comparableUnit) {
        System.out.println(comparableUnit+",List:"+comparableUnion);
        return comparableUnion.contains(comparableUnit);
    }

    @Override
    public int hashCode() {
        int result = 1;
        for (ComparableUnit unit : comparableUnion) {
            result = 31 * result + ((null == unit) ? 0 : unit.hashCode());
        }
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (null == obj) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof ComparableUnion)) {
            return false;
        }
        ComparableUnion other = (ComparableUnion) obj;
        if (other.getComparableUnion().size() != comparableUnion.size()) {
            return false;
        }
        int len = other.getComparableUnion().size();
        for (int i=0; i<len; i++) {
            if (!Objects.equal(other.getComparableUnion().get(i), getComparableUnion().get(i))) {
                return false;
            }
        }
        return true;
    }

 }
